#include <iostream>
#include <event2/event.h>
#include <event2/listener.h>
#include <string.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <string>
#ifndef _WIN32
#include <signal.h>
#endif
using namespace std;

//数据来了 不处理的话 会一直触发 等程序员处理
//处理了缓冲区就 不会一直触发了
enum bufferevent_filter_result filter_in(
        struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit,
        enum bufferevent_flush_mode mode, void *ctx){
        cout<<"filter_in"<<endl;
        
        //读取并清理原数据
        char data[1024] = {0};
        int len = evbuffer_remove(src, data, sizeof(data)-1);

        //把所有字母转成大写
        for (int i = 0; i < len; i++){
                data[i] = toupper(data[i]);
        }

        //取出来处理 再塞到输入缓冲区
        evbuffer_add(dst, data, len);

        return BEV_OK;
}

enum bufferevent_filter_result filter_out(
        struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit,
        enum bufferevent_flush_mode mode, void *ctx){
        
        cout<<"filter_out"<<endl;
        //读取并清理原数据
        char data[1024] = {0};
        evbuffer_remove(src, data, sizeof(data)-1);

        string  str = "";
        str += "=====================\n";
        str += data;
        str += "=====================\n";

        //取出来处理 再写到输出缓冲区
        evbuffer_add(dst,  str.c_str(), str.size());

        return BEV_OK;
}

void read_cb(bufferevent *bev, void *arg){
        cout<<"read_cb"<<endl;
        char data[1024] = {0};
        int len = bufferevent_read(bev, data, sizeof(data)-1);
        cout<<data<<endl;

        //回复客户消息，经过输出过滤器
        bufferevent_write(bev, data, len);
}

void write_cb(bufferevent *bev, void *arg){
        cout<<"write_cb"<<endl;
}

void event_cb(bufferevent *bev, short what, void *arg){
        cout<<"event_cb"<<endl;
}

void listener_cb(struct evconnlistener *ev, evutil_socket_t lfd, 
                                struct sockaddr *sin, int socklen, void *arg){
        sockaddr_in *csin = (sockaddr_in *)sin;
        char ip[16] = {0};
        evutil_inet_ntop(sin->sa_family,  &csin->sin_addr, ip, sizeof(ip)-1);
        cout<<"client ip is "<<ip<<" port is "<<ntohs(csin->sin_port)<<endl;

        event_base *base = (event_base*)arg;
        //创建buffervent 
        bufferevent *bev = bufferevent_socket_new(base, lfd, BEV_OPT_CLOSE_ON_FREE);
        //绑定bufferevent filter
        bufferevent *bev_filter = bufferevent_filter_new(bev, 
                filter_in,  //输入过滤函数
                filter_out, //输出过滤函数
                BEV_OPT_CLOSE_ON_FREE, //关闭filter同时关闭bufferevent
                NULL, //清理的回调函数
                NULL//传递给回调函数的参数
                );
        
        //设置bufferevent的回调 因为有了filter所以直接在filter上设置回调事件
        bufferevent_setcb(bev_filter, read_cb, write_cb, event_cb, NULL); 
        
        bufferevent_enable(bev_filter, EV_READ|EV_WRITE);
}

int main(int argc, char const *argv[]){
#ifdef _WIN32
        //初始化socket库
        WSADATA wsa;
        WSAStartup(MAKEWORD(2,2), &wsa);
#else
        //忽略管道信号 发送数据给已关闭的socket
        if(signal(SIGPIPE,SIG_IGN) == SIG_IGN){
                return 1;
        }
#endif
        event_base *base = event_base_new();

        //创建网络服务器
        sockaddr_in sin;
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(8080);

        evconnlistener *ev = evconnlistener_new_bind(base,  listener_cb, base,
                LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE_PORT,
                -1, (sockaddr*)&sin, sizeof(sin));

        event_base_dispatch(base);

        evconnlistener_free(ev);

        event_base_free(base);

        return 0;
}
